package treeview.table;

import search.Visitor;
import treeview.AbstractNodeView;
import treeview.NodeView;

import java.awt.*;

/**
 * Created by Pavel Nikolaev
 */
public final class TableView extends AbstractNodeView {
    private int myRowNumber;
    private int myColumnNumber;
    private NodeView[][] myRows;
    private NodeView[][] myColumns;

    public TableView(int rows, int columns) {
        this.myRowNumber = rows;
        this.myColumnNumber = columns;
        myRows = new NodeView[rows][columns];
        myColumns = new NodeView[columns][rows];
    }

    public void fitIntoWidth(Graphics g, int widthToFitInto) {
        int columnWidth = widthToFitInto/myColumnNumber;
        for (int i = 0; i < myRowNumber; ++i)
            for (int j = 0; j < myColumnNumber; ++j)
                myRows[i][j].fitIntoWidth(g, columnWidth);


        // columns width alignment
        alignColumnsWidth(g);
        // rows height alignment
        alignRowsHeight();
    }

    private void alignColumnsWidth(Graphics g) {
        myWidth = 0;
        for (int j = 0; j < myColumnNumber; ++j) {
            int columnWidth = 0;
            NodeView[] column = getColumn(j);
            for (int i = 0; i < myRowNumber; ++i) {
                int cellWidth = column[i].getWidth();
                if (cellWidth > columnWidth) columnWidth = cellWidth;
            }
            myWidth += columnWidth;
            for (int i = 0; i < myRowNumber; ++i) {
                int cellWidth = column[i].getWidth();
                if (cellWidth != columnWidth) {
                    column[i].fitIntoWidth(g, columnWidth);
                    column[i].setWidth(columnWidth);
                }
            }
        }
    }

    private void alignRowsHeight() {
        myHeight = 0;
        for (int i = 0; i < myRowNumber; ++i) {
            int rowHeight = 0;
            NodeView[] row = getRow(i);
            for (int j = 0; j < myColumnNumber; ++j) {
                int cellHeight = row[j].getHeight();
                if (cellHeight > rowHeight)  rowHeight = cellHeight;
            }
            myHeight += rowHeight;
            for (int j = 0; j < myColumnNumber; ++j) {
                int cellHeight = row[j].getHeight();
                if (cellHeight != rowHeight) row[j].setHeight(rowHeight);
            }
        }
    }



    public void drawAt(Graphics g, int x, int y) {
        int cell_y = y;
        for (int i = 0; i < myRowNumber; ++i) {
            int cell_x = x;
            NodeView[] row = getRow(i);
            for (int j = 0; j < myColumnNumber; ++j) {
                NodeView cell = row[j];
                cell.drawAt(g, cell_x, cell_y);
                cell_x += cell.getWidth();
            }
            cell_y += row[0].getHeight();
        }
    }

    public void paint(Graphics g) {
        for (int i = 0; i < myRowNumber; ++i)
            for (int j = 0; j < myColumnNumber; ++j)
                myRows[i][j].paint(g);
    }

    public void setCellView(NodeView view, int row, int column) {
        myRows[row][column] = view;
        myColumns[column][row] = view;
    }

    private NodeView[] getRow(int index) {
        return myRows[index];
    }

    private NodeView[] getColumn(int index) {
        return myColumns[index];
    }

    @Override
    public void setLocation(int x, int y) {
        myX = x;
        myY = y;
        int cell_y = y;
        for (int i = 0; i < myRowNumber; ++i) {
            int cell_x = x;
            NodeView[] row = getRow(i);
            for (int j = 0; j < myColumnNumber; ++j) {
                NodeView cell = row[j];
                cell.setLocation(cell_x, cell_y);
                cell_x += cell.getWidth();
            }
            cell_y += row[0].getHeight();
        }
    }

    @Override
    public void accept(Visitor visitor) {
        if (visitor.visitTableView(this)) {
            for (int i = 0; i < myRowNumber; ++i)
                for (int j = 0; j < myColumnNumber; ++j)
                    myRows[i][j].accept(visitor);
        }
    }

    @Override
    public void print(int level) {
        super.print(level);
        for (int i = 0; i < myRowNumber; ++i)
            for (int j = 0; j < myColumnNumber; ++j)
                myRows[i][j].print(level + 1);
    }
}

